package com.zmn.oms.zmn.business.impl.work;

import com.google.common.collect.Lists;
import com.zmn.common.utils.date.DateUtil;
import com.zmn.common.utils.number.NumberUtil;
import com.zmn.oms.business.interfaces.grid.GridGroupDistributeBService;
import com.zmn.oms.business.interfaces.orderstock.OrderStockBService;
import com.zmn.oms.common.constant.ConfOrderDutyConsts;
import com.zmn.oms.common.constant.OrderConsts;
import com.zmn.oms.common.constant.OrderDistributeConsts;
import com.zmn.oms.common.constant.OrderGateTypeConsts;
import com.zmn.oms.common.dro.conf.distribute.DistributeArgsDRO;
import com.zmn.oms.common.dro.conf.distribute.DistributeConfigDRO;
import com.zmn.oms.common.dro.conf.distribute.PlatDirectlyDistributeArgsDRO;
import com.zmn.oms.common.exception.OmsBaseException;
import com.zmn.oms.model.dto.orderstock.StockWhiteDTO;
import com.zmn.oms.model.dto.work.schedule.WorkOrderScheduleQuery;
import com.zmn.oms.model.entity.changerecord.OrderChangeRecord;
import com.zmn.oms.model.entity.conf.orderduty.OrderDuty;
import com.zmn.oms.model.entity.conf.orderduty.OrderDutyQuery;
import com.zmn.oms.model.entity.work.OrderWork;
import com.zmn.oms.model.vo.work.schedule.OrderScheduleVO;
import com.zmn.oms.model.vo.work.schedule.ScheduleDayVo;
import com.zmn.oms.services.interfaces.changerecord.OrderChangeRecordService;
import com.zmn.oms.services.interfaces.conf.orderduty.OrderDutyService;
import com.zmn.oms.services.interfaces.work.OrderWorkService;
import com.zmn.oms.zmn.business.interfaces.work.ZsOrderWorkScheduleBService;
import com.zmn.oms.zmn.business.interfaces.work.customwork.ZsDistributeWorkBService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.*;

/**
 * 类描述：工单排期
 *
 * @author liuying
 * @date 2018/12/11 17:43
 */
@Service
@Slf4j
public class ZsOrderWorkScheduleBServiceImpl implements ZsOrderWorkScheduleBService {

    @Resource
    private OrderChangeRecordService orderChangeRecordService;

    @Autowired
    OrderWorkService orderWorkService;
    @Autowired
    OrderStockBService orderStockBService;
    @Autowired
    private OrderDutyService orderDutyService;
    @Autowired
    private GridGroupDistributeBService gridGroupDistributeBService;
    @Autowired
    private ZsDistributeWorkBService zsDistributeWorkBService;

    @Override
    public List<ScheduleDayVo> getScheduleDayList() {
        List<ScheduleDayVo> list = Lists.newArrayList();
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(new Date());

        int nowTime = Integer.parseInt(DateUtil.toString(calendar.getTime(), "HHmm"));
        int lastTime = 2230;
        boolean nextDay = false;
        if (nowTime >= lastTime) {
            nextDay = true;
        }
        int day = calendar.get(Calendar.DAY_OF_WEEK) - 1;
        day = (day == 0) ? 6 : day - 1;
        for (int i = 0 - day; i < 60; i++) {
            ScheduleDayVo scheduleDayVo = getDate(i);
            scheduleDayVo.setDisabled(i < 0);
            scheduleDayVo.setNowDate(i == 0);
            scheduleDayVo.setIndex(i);
            // 默认是否选中，默认预约时间是当天,可选预约时间推后1个半小时。
            if (!nextDay && scheduleDayVo.isNowDate()) {
                scheduleDayVo.setDefaultActive(true);
            } else if (nextDay && i == 1) {
                scheduleDayVo.setDefaultActive(true);
            } else {
                scheduleDayVo.setDefaultActive(false);
            }
            list.add(scheduleDayVo);
        }
        return list;
    }

    @Override
    public OrderScheduleVO getScheduleTimes(String scheDate, Integer scale) {
        OrderScheduleVO orderScheduleVO = new OrderScheduleVO();
        orderScheduleVO.setDate(scheDate);
        orderScheduleVO.setNowTime(DateUtil.getNowFormatted(DateUtil.FORMAT_DEFAULT));

        // 获取预约时间
        Date curDate = DateUtil.getNow();
        // curDate = DateUtil.parse("2019-01-10 22:35:23", DateUtil.FORMAT_DEFAULT);

        int curDay = Integer.parseInt(DateUtil.toString(curDate, DateUtil.FORMAT_DATE2));
        int curNextDay = Integer.parseInt(DateUtil.toString(DateUtil.addDays(curDate, 1), DateUtil.FORMAT_DATE2));
        int scheDay = Integer.parseInt(DateUtil.toString(DateUtil.parse(scheDate, DateUtil.FORMAT_DATE), DateUtil.FORMAT_DATE2));

        if (scheDay < curDay) {
            orderScheduleVO.setTimes(OrderConsts.ORDER_SCHE_NONE_TIMES_96);
        } else {
            //限制服务的时间（半小时/单位）
            int limitServiceTimes = 0;
            if (scheDay == curDay) {
                limitServiceTimes = this.getLimitServiceTimes(curDate);
            }
            String scheTimes = OrderConsts.ORDER_SCHE_ALL_TIMES_96;
            if (limitServiceTimes > 0) {
                scheTimes = OrderConsts.ORDER_SCHE_NONE_TIMES_96.substring(0, limitServiceTimes) + OrderConsts.ORDER_SCHE_ALL_TIMES_96.substring(limitServiceTimes);
            }
            orderScheduleVO.setTimes(scheTimes);

            // 设置当天默认时间
            if (scheDay == curDay) {
                int activeIndex = limitServiceTimes + 3;
                if (NumberUtil.isNotNullOrZero(scale)) {
                    activeIndex += scale;
                }
                if (activeIndex <= 96) {
                    orderScheduleVO.setDefaultActiveIndex(activeIndex);
                }
            } else if (scheDay == curNextDay) {
                int nowLimitServiceTimes = getLimitServiceTimes(curDate);
                if (nowLimitServiceTimes > 44) {
                    int activeIndex = 3 - (96 - nowLimitServiceTimes);
                    orderScheduleVO.setDefaultActiveIndex(activeIndex);
                }
            }
        }
        return orderScheduleVO;
    }

    @Override
    public List<ScheduleDayVo> getCustomerScheduleDayList() {
        List<ScheduleDayVo> list = this.getScheduleDayList();

        // 当天
        Optional<ScheduleDayVo> optional = list.stream().filter(item -> item.isNowDate() && item.isDefaultActive()).findAny();
        if (optional.isPresent()) {

            // 判断当天是否可以预约
            ScheduleDayVo nowScheduleDayVo = optional.get();
            OrderScheduleVO orderScheduleVO = this.getCustomerScheduleTimes(nowScheduleDayVo.getDate());

            if (orderScheduleVO.getDefaultActiveIndex() < 0) {
                // 当天无法预约，设置到下一天
                Optional<ScheduleDayVo> nextOptional = list.stream().filter(item -> item.getIndex() > nowScheduleDayVo.getIndex() && !item.isDisabled()).findAny();
                if (nextOptional.isPresent()) {
                    nextOptional.get().setDefaultActive(true);
                }
            }
        }

        return list;
    }

    @Override
    public OrderScheduleVO getCustomerScheduleTimes(String scheDate) {
        Date curDate = new Date();

        // curDate = DateUtil.parse("2019-03-05 15:30:00");

        OrderScheduleVO orderScheduleVO = new OrderScheduleVO();
        orderScheduleVO.setDate(scheDate);
        orderScheduleVO.setNowTime(DateUtil.getNowFormatted(DateUtil.FORMAT_DEFAULT));

        String scheStr = OrderConsts.ORDER_SCHE_ALL_TIMES;

        // 第二天
        Date afterDate = DateUtil.addDays(curDate, 1);
        //  当前小时数
        int hour = DateUtil.getHour(curDate);

        //限制服务的时间（半小时/单位）
        int limitServiceTimes = 0;

        // 预约时间是当天,可选预约时间推后1个半小时。
        if (scheDate.equals(DateUtil.toString(curDate, DateUtil.FORMAT_DATE))) {
            // 分钟数
            int minute = DateUtil.getMinute(curDate);
            // 当天9点前不能下10点前的单子
            if (hour <= 8) {
                limitServiceTimes = 10 * 2;
            } else {
                limitServiceTimes = hour * 2;
                if (minute > 0 && minute <= 30) {
                    limitServiceTimes++;
                } else if (minute > 30) {
                    limitServiceTimes += 2;
                }

                limitServiceTimes += 3;

                if (limitServiceTimes > 47) {
                    limitServiceTimes = 47;
                }
            }
        } else if (scheDate.equals(DateUtil.toString(afterDate, DateUtil.FORMAT_DATE))) {
            // 当天超18点不能下第二天10点前的工单
            if (hour >= 18) {
                // 上午十点
                limitServiceTimes = 10 * 2;
            }
        }

        if (limitServiceTimes > 0) {
            scheStr = OrderConsts.ORDER_SCHE_NONE_TIMES.substring(0, limitServiceTimes) + scheStr.substring(limitServiceTimes);
        }

        int workStartTime = 17;
        int workEndTime = 35;

        scheStr = OrderConsts.ORDER_SCHE_NONE_TIMES.substring(0, workStartTime) +
                scheStr.substring(workStartTime, workEndTime) +
                OrderConsts.ORDER_SCHE_NONE_TIMES.substring(workEndTime);

        orderScheduleVO.setTimes(scheStr);
        orderScheduleVO.setDefaultActiveIndex(scheStr.indexOf("1"));

        return orderScheduleVO;
    }
    /**
     * 获取默认预约时间
     * @see OrderGateTypeConsts#GATE_PLAT_BACKSTAGE
     *
     * @param geteType 平台
     * @return
     */
    @Override
    public String getDefaultDutyTime(int plat, int geteType) {
        // 获取默认选中的日期
        List<ScheduleDayVo> scheduleDayVoList = this.getScheduleDayList();
        Optional<ScheduleDayVo> optional = scheduleDayVoList.stream().filter(item -> item.isDefaultActive()).findAny();
        if (optional.isPresent()) {
            String dutyDay = optional.get().getDate();
            // 获取默认选中的时间
            OrderScheduleVO orderScheduleVO = this.getScheduleTimes(dutyDay, null);
            Calendar calendar = Calendar.getInstance();
            calendar.setTime(DateUtil.parse(dutyDay, DateUtil.FORMAT_DATE));
            calendar.set(Calendar.SECOND, 0);
            calendar.set(Calendar.MINUTE, 0);
            calendar.set(Calendar.HOUR_OF_DAY, 0);
            calendar.add(Calendar.MINUTE, orderScheduleVO.getDefaultActiveIndex() * 30);

            Date date = calendar.getTime();
            String dutyTime = DateUtil.toString(date);

            // 处理时间范围
            if (this.validateDutyTime(plat, geteType, date)) {
                return dutyTime;
            }
        }
        return null;
    }

    @Override
    public String getDefaultHalfPointDutyTime(int plat, int geteType) {
        return getDefaultHalfPoint(plat, geteType);
    }

    @Override
    public String getBackStageDefaultDutyTime(WorkOrderScheduleQuery workOrderScheduleQuery) {

        // 获取派单配置
        OrderWork orderWork = new OrderWork();
        orderWork.setPlatWork(workOrderScheduleQuery.getPlatWork());
        orderWork.setPlat(workOrderScheduleQuery.getPlat());
        orderWork.setBizType(workOrderScheduleQuery.getBizType());
        orderWork.setCityId(workOrderScheduleQuery.getCityId());
        orderWork.setServProductGroupId(workOrderScheduleQuery.getProductGroupId());
        DistributeConfigDRO distributeConfigDRO = zsDistributeWorkBService.getDistributeConfig(orderWork);

        // 平台直派
        if (Objects.equals(distributeConfigDRO.getDistributeWay(), OrderDistributeConsts.DISTRIBUTE_WAY_PLAT)) {
            PlatDirectlyDistributeArgsDRO platDirectlyDistributeArgsDRO = distributeConfigDRO.getPlatDirectlyDistributeArgsDRO();
            return this.calcDutyTime(platDirectlyDistributeArgsDRO.getAutoTimeStart(), platDirectlyDistributeArgsDRO.getAutoTimeEnd());
        } else {
            DistributeArgsDRO distributeArgsDRO = distributeConfigDRO.getDistributeArgsDRO();
            return this.calcDutyTime(distributeArgsDRO.getAutoTimeStart(), distributeArgsDRO.getAutoTimeEnd());
        }
    }

    /**
     * 若当前时间不在自动派单时间内，则下单时间默认到第二天早上8点；
     * 若当前时间在自动派单时间内，则按照当前时间增加2.5小时进行计算，情况如下：
     *    若增加后的时间在自动派单时间内，则下单时间默认为增加后的时间；
     *    若增加后的时间不在自动派单时间内，则下单时间默认到第二天早上8点；
     * @param startAutoTime
     * @param endAutoTime
     * @return
     */
    private String calcDutyTime(String startAutoTime, String endAutoTime) {

        Calendar calendar = Calendar.getInstance();
        System.out.println(DateUtil.dateFormatToString(calendar.getTime(), DateUtil.FORMAT_DEFAULT));
        // 先判断分钟刻度，目前后台是15分钟一刻度
        int nowMinute = calendar.get(Calendar.MINUTE);
        if (nowMinute <= 15) {
            calendar.set(Calendar.MINUTE, 15);
        } else if (15 < nowMinute && nowMinute <= 30){
            calendar.set(Calendar.MINUTE, 30);
        } else if (30 < nowMinute && nowMinute <= 45) {
            calendar.set(Calendar.MINUTE, 45);
        } else {
            calendar.add(Calendar.HOUR_OF_DAY, 1);
            calendar.set(Calendar.MINUTE, 0);
        }
        calendar.set(Calendar.SECOND, 0);
        calendar.set(Calendar.MILLISECOND, 0);
        System.out.println(DateUtil.dateFormatToString(calendar.getTime(), DateUtil.FORMAT_DEFAULT));

        // 取当前预约时间
        int nowTime = Integer.parseInt(DateUtil.dateFormatToString(calendar.getTime(), "HH:mm")
                .replace(":", ""));

        // 增加2.5小时
        calendar.add(Calendar.HOUR_OF_DAY, 2);
        calendar.add(Calendar.MINUTE, 30);

        int endTime = Integer.parseInt(endAutoTime.replace(":", ""));
        int addTime = Integer.parseInt(DateUtil.dateFormatToString(calendar.getTime(), "HH:mm")
                .replace(":", ""));
        System.out.println("addTime:" + addTime + ",endTime:" + endTime);

        // 当天最晚时间为21:30
        int todayEndTime = Integer.parseInt("2130");

        // 如果当前时间+2.5小时>自动派单结束时间
        if (addTime >= endTime || nowTime >= todayEndTime) {
            Calendar tomorrow = Calendar.getInstance();
            tomorrow.add(Calendar.DAY_OF_MONTH, 1);
            tomorrow.set(Calendar.HOUR_OF_DAY, 8);
            tomorrow.set(Calendar.MINUTE, 0);
            tomorrow.set(Calendar.SECOND, 0);
            tomorrow.set(Calendar.MILLISECOND, 0);
            return DateUtil.dateFormatToString(tomorrow.getTime(), DateUtil.FORMAT_DEFAULT);
        } else {
            return DateUtil.dateFormatToString(calendar.getTime(), DateUtil.FORMAT_DEFAULT);
        }
    }

    /**
     * 获取默认预约半点时间，当前时间，往后推1小时，取最近的半点时刻返回
     * 若：最近半点超过预约设置的下限，则返还第二天最早的半点
     * 若：最近半点没有到预约设置的上限，则返回当天最早的半点
     * 示例：当前是15.48，往后推1小时是16.48，最近的半点则是：17.30
     *
     * @param plat     平台标示
     * @param geteType 品台常量配置
     * @return
     */
    public String getDefaultHalfPoint(int plat, int geteType) {
        Date nowTime = new Date();
        int nowHH = Integer.parseInt(DateUtil.toString(nowTime, "HH")); // 格式 HH

        // 后台下单，20：00后，默认时间为第二天8:00
        if (Objects.equals(OrderGateTypeConsts.GATE_PLAT_BACKSTAGE, geteType)) {
            if (nowHH >= 20) {
                return DateUtil.toString(DateUtil.addDays(nowTime, 1), "yyyy-MM-dd 08:00:00");
            }
        }

        OrderDuty orderDuty = this.callServeForAppointmentSetting(plat, geteType, ConfOrderDutyConsts.APPOINTMENT_OR_CHANGE_APPOINTMENT);
        if (orderDuty == null) {
            Date duty = round(new Date(), 3);
            if (duty == null) {
                return null;
            }
            return DateUtil.toString(duty);
        }

        String startTime = orderDuty.getStartTime(); // 格式 HH:mm
        String endTime = orderDuty.getEndTime(); // 格式 HH:mm
        String nowHour = DateUtil.toString(nowTime, "HH:mm"); // 格式 HH:mm
        if (startTime == null || endTime == null) {
            return null;
        }

        String dutyHour = null;
        String nowDate = DateUtil.toString(nowTime, "yyyy-MM-dd");

        int now = Integer.parseInt(nowHour.replace(":", ""));
        int min = Integer.parseInt(startTime.replace(":", ""));
        int max = Integer.parseInt(endTime.replace(":", ""));

        if (now > max) {
            Date nowMinuteDate = DateUtil.parse(startTime, "HH:mm");
            dutyHour = DateUtil.toString(round(nowMinuteDate, DateUtil.UNIT_MINUTE, 0), "HH:mm");
            nowDate = DateUtil.toString(DateUtil.addDays(new Date(), 1), "yyyy-MM-dd");
        } else if (now < min) {
            Date time = DateUtil.parse(startTime, "HH:mm");
            dutyHour = DateUtil.toString(round(time, DateUtil.UNIT_MINUTE, 0), "HH:mm");
        } else if (now > min && now < max) {
            Date nowMinuteDate = DateUtil.parse(nowHour, "HH:mm");
            dutyHour = DateUtil.toString(round(nowMinuteDate, DateUtil.UNIT_MINUTE), "HH:mm");

            boolean is = DateUtil.isBetween(startTime, endTime, dutyHour, "HH:mm");
            int duty = Integer.parseInt(dutyHour.replace(":", ""));
            if (!is && duty > max) {
                Date time = DateUtil.parse(startTime, "HH:mm");
                dutyHour = DateUtil.toString(round(time, DateUtil.UNIT_MINUTE, 0), "HH:mm");
                nowDate = DateUtil.toString(DateUtil.addDays(new Date(), 1), "yyyy-MM-dd");
            }
        }

        if (dutyHour == null) {
            return null;
        }

        String dutyTime = String.format("%s %s:00", nowDate, dutyHour);

       /* String endDate = String.format("%s %s", nowDay, endTime);
        boolean isAfter = DateUtil.parse(dutyTime, DateUtil.FORMAT_DATETIME).after(DateUtil.parse(endDate));
        if (isAfter) {
            */// return null;
        // }
        return dutyTime;
    }

    public Date round(Date date, int unitType) {
        return round(date, unitType, 2);
    }

    public Date round(Date date, int unitType, int hour) {
        int minHour = 1;
        int maxHour = 2;
        if (Objects.nonNull(hour) && hour == 0) {
            minHour = hour;
            maxHour = 1;
        }
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        if (DateUtil.UNIT_MINUTE == unitType) {
            int minute = calendar.get(Calendar.MINUTE);
            if ((0 <= minute) && (minute < 30)) {
                calendar.add(Calendar.HOUR, minHour);
                calendar.set(Calendar.MINUTE, 30);
                calendar.set(Calendar.SECOND, 0);
            } else {
                calendar.set(Calendar.MINUTE, 0);
                if (30 <= minute) {
                    calendar.add(Calendar.HOUR, maxHour);
                    calendar.add(Calendar.MINUTE, 30);
                    calendar.set(Calendar.SECOND, 0);
                }
            }
        }
        return calendar.getTime();
    }

    @Override
    public String processScheduleTimes(Long orderId, Integer plat, int gateType, String times){
        if (NumberUtil.isNotNullOrZero(orderId) && Objects.isNull(plat)) {
            OrderWork orderWork = orderWorkService.findOrderWorkByKey(orderId, orderId);
            plat = orderWork.getPlat();
        }

        if (plat == null || StringUtils.isBlank(times)) {
            return times;
        }

        // 判断改约的操作时间是否在规定的时间范围内
        if (orderId != null) {
            OrderDuty orderDuty = this.callServeForAppointmentSetting(plat, gateType, ConfOrderDutyConsts.APPOINTMENT_OR_CHANGE_CHANGE);
            boolean canOperate = this.validateOperateDutyTime(orderDuty);
            if (canOperate == false) {
                return OrderConsts.ORDER_SCHE_NONE_TIMES;
            }
        }

        // 调服务查通用设置的预约时间
        OrderDuty orderDuty = this.callServeForAppointmentSetting(plat, gateType, ConfOrderDutyConsts.APPOINTMENT_OR_CHANGE_APPOINTMENT);
        if (orderDuty == null) {
            return times;
        }

        // 预约时间范围
        return this.filterScheTimes(orderDuty.getStartTime(), orderDuty.getEndTime(), times);
    }

    /**
     * 判断预约时间是否在设置的区间内
     *
     * @param plat     平台
     * @param gateType 入口
     * @param dutyTime 预约时间
     * @return true:在预约时间范围
     */
    protected boolean validateDutyTime(Integer plat, int gateType, Date dutyTime) {
        if (Objects.isNull(dutyTime)) {
            return false;
        }

        OrderDuty orderDuty = this.callServeForAppointmentSetting(plat, gateType, ConfOrderDutyConsts.APPOINTMENT_OR_CHANGE_CHANGE);
        if (orderDuty != null && StringUtils.isNotBlank(orderDuty.getStartTime()) && StringUtils.isNotBlank(orderDuty.getEndTime())) {
            String nowMinute = DateUtil.toString(dutyTime, "HH:mm");
            if (this.isBetweenMinute(nowMinute, orderDuty.getStartTime(), orderDuty.getEndTime()) == false) {
                return false;
            }
        }

        return true;
    }

    /**
     * 修改预约时间时检查
     * @param orderWork  工单信息
     * @param gateType   入口
     * @param newDutyTime  新的预约时间
     * @throws OmsBaseException
     */
    @Override
    public void validateModifyDutyTime(OrderWork orderWork, int gateType, Date newDutyTime) throws OmsBaseException {

        // 参数判断
        if (Objects.isNull(orderWork) || Objects.isNull(newDutyTime)) {
            throw new OmsBaseException("修改预约时间参数错误");
        }

        if (Objects.equals(orderWork.getDutyTime(), newDutyTime)) {
            return;
        }

        // 判断操作时间超出规定的操作时间范围
        OrderDuty orderDuty = this.callServeForAppointmentSetting(orderWork.getPlat(), gateType,
                ConfOrderDutyConsts.APPOINTMENT_OR_CHANGE_CHANGE);
        if (!this.validateOperateDutyTime(orderDuty)) {
            throw new OmsBaseException("改约操作时间超出规定的操作时间范围");
        }

        // 判断改约时间是否超出规定的预约时间范围
        if (orderDuty != null && newDutyTime != null && StringUtils.isNotBlank(orderDuty.getStartTime())
                && StringUtils.isNotBlank(orderDuty.getEndTime())) {
            String nowMinute = DateUtil.toString(newDutyTime, "HH:mm");
            if (this.isBetweenMinute(nowMinute, orderDuty.getStartTime(), orderDuty.getEndTime()) == false) {
                throw new OmsBaseException("改约时间超出规定的预约时间范围");
            }
        }

        // 判断改约次数
        StockWhiteDTO stockWhiteDTO = StockWhiteDTO.builder()
                .workCityId(orderWork.getCityId())
                .masterId(orderWork.getCityId())
                .build();

        if (!orderStockBService.isWhiteByAllConditions(stockWhiteDTO) &&
                !this.checkModifyCount(orderWork.getOrderId(), orderDuty)) {
            throw new OmsBaseException("超出规定改约次数，如需改约，请联系后台改约");
        }
    }

    @Override
    public void validateDutyTime(Long orderId, Integer plat, int gateType, Date newDutyTime) throws OmsBaseException {

        OrderWork orderWork = null;
        Integer masterId = null;

        if (Objects.nonNull(orderId)) {
            orderWork = orderWorkService.findOrderWorkByKey(orderId, orderId);
            plat = orderWork.getPlat();
            masterId = orderWork.getMasterId();
        }

        // 只校验新单、返修单
        // 校验预约时间范围（新单只校验时间范围）
        // 调服务查通用设置的预约时间、改约时间、改约次数
        OrderDuty orderDuty = this.callServeForAppointmentSetting(plat, gateType, ConfOrderDutyConsts.APPOINTMENT_OR_CHANGE_APPOINTMENT);
        if (orderDuty != null && newDutyTime != null && StringUtils.isNotBlank(orderDuty.getStartTime()) && StringUtils.isNotBlank(orderDuty.getEndTime())) {
            String nowMinute = DateUtil.toString(newDutyTime, "HH:mm");
            if (this.isBetweenMinute(nowMinute, orderDuty.getStartTime(), orderDuty.getEndTime()) == false) {
                throw new OmsBaseException("预约时间超出规定的预约时间范围");
            }
        }
        // 新单校验结束，return
        if (orderId == null) {
            return;
        }
        if (Objects.isNull(orderWork.getDutyTime()) || Objects.isNull(newDutyTime) || Objects.equals(orderWork.getDutyTime(), newDutyTime)) {
            return;
        }
        // 判断改约操作时间，即当前订单修改时间是否在时间范围内
        orderDuty = this.callServeForAppointmentSetting(orderWork.getPlat(), gateType, ConfOrderDutyConsts.APPOINTMENT_OR_CHANGE_CHANGE);
        boolean canOperate = this.validateOperateDutyTime(orderDuty);
        if (!canOperate) {
            throw new OmsBaseException("改约操作时间超出规定的操作时间范围");
        }
        // 判断改约次数
        StockWhiteDTO stockWhiteDTO = StockWhiteDTO.builder()
                .workCityId(orderWork.getCityId())
                .masterId(masterId)
                .build();
        boolean whiteByAllConditions = orderStockBService.isWhiteByAllConditions(stockWhiteDTO);
        if (!whiteByAllConditions) {
            boolean modifyDutyTime = this.checkModifyCount(orderId, orderDuty);
            if (!modifyDutyTime) {
                throw new OmsBaseException("超出规定改约次数，如需改约，请联系后台改约");
            }
        }
    }

    @Override
    public boolean validateOperateDutyTime(int plat, int gateType) {
        OrderDuty orderDuty = this.callServeForAppointmentSetting(plat, gateType, ConfOrderDutyConsts.APPOINTMENT_OR_CHANGE_CHANGE);
        return this.validateOperateDutyTime(orderDuty);
    }

    @Override
    public OrderScheduleVO getScheduleTimesNew(WorkOrderScheduleQuery workOrderScheduleQuery) {
        OrderScheduleVO orderScheduleVO = new OrderScheduleVO();
        orderScheduleVO.setDate(workOrderScheduleQuery.getScheDate());
        orderScheduleVO.setNowTime(DateUtil.getNowFormatted(DateUtil.FORMAT_DEFAULT));

        // 获取预约时间
        Date curDate = DateUtil.getNow();
        // curDate = DateUtil.parse("2019-01-10 22:35:23", DateUtil.FORMAT_DEFAULT);

        int curDay = Integer.parseInt(DateUtil.toString(curDate, DateUtil.FORMAT_DATE2));
        int curNextDay = Integer.parseInt(DateUtil.toString(DateUtil.addDays(curDate, 1), DateUtil.FORMAT_DATE2));
        int scheDay = Integer.parseInt(DateUtil.toString(DateUtil.parse(workOrderScheduleQuery.getScheDate(), DateUtil.FORMAT_DATE), DateUtil.FORMAT_DATE2));

        String scheTimes;
        if (scheDay < curDay) {
            scheTimes = OrderConsts.ORDER_SCHE_NONE_TIMES_96;
            orderScheduleVO.setTimes(OrderConsts.ORDER_SCHE_NONE_TIMES_96);
        } else {
            // 2022/04/08 huangchao 选择预约逻辑变更 新增网格组派单逻辑调整
            if (workOrderScheduleQuery.getIsGrid() && ! isCalculateSchedule(workOrderScheduleQuery, curDate)) {
                scheTimes = OrderConsts.ORDER_SCHE_NONE_TIMES_96;
                orderScheduleVO.setTimes(scheTimes);
            }else {
                //限制服务的时间（半小时/单位）
                int limitServiceTimes = 0;
                if (scheDay == curDay) {
                    limitServiceTimes = this.getLimitServiceTimes(curDate);
                }
                scheTimes = OrderConsts.ORDER_SCHE_ALL_TIMES_96;
                if (limitServiceTimes > 0) {
                    scheTimes = OrderConsts.ORDER_SCHE_NONE_TIMES_96.substring(0, limitServiceTimes) + OrderConsts.ORDER_SCHE_ALL_TIMES_96.substring(limitServiceTimes);
                }
                orderScheduleVO.setTimes(scheTimes);

                // 设置当天默认时间
                if (scheDay == curDay) {
                    int activeIndex = limitServiceTimes + 3;
                    if (activeIndex <= 96) {
                        orderScheduleVO.setDefaultActiveIndex(activeIndex);
                    }
                } else if (scheDay == curNextDay) {
                    int nowLimitServiceTimes = getLimitServiceTimes(curDate);
                    if (nowLimitServiceTimes > 44) {
                        int activeIndex = 3 - (96 - nowLimitServiceTimes);
                        orderScheduleVO.setDefaultActiveIndex(activeIndex);
                    }
                }
            }
        }

        Long orderId = workOrderScheduleQuery.getWorkId();
        Integer plat = workOrderScheduleQuery.getPlatWork();
        if (NumberUtil.isNotNullOrZero(orderId) && Objects.isNull(plat)) {
            OrderWork orderWork = orderWorkService.findOrderWorkByKey(orderId, orderId);
            plat = orderWork.getPlat();
        }

        if (plat == null || StringUtils.isBlank(scheTimes)) {
            return orderScheduleVO;
        }

        // 判断改约的操作时间是否在规定的时间范围内
        if (orderId != null) {
            OrderDuty orderDuty = this.callServeForAppointmentSetting(plat, OrderGateTypeConsts.GATE_PLAT_BACKSTAGE, ConfOrderDutyConsts.APPOINTMENT_OR_CHANGE_CHANGE);
            boolean canOperate = this.validateOperateDutyTime(orderDuty);
            if (canOperate == false) {
                scheTimes = OrderConsts.ORDER_SCHE_NONE_TIMES;
                orderScheduleVO.setTimes(scheTimes);
                return orderScheduleVO;
            }
        }

        // 调服务查通用设置的预约时间
        OrderDuty orderDuty = this.callServeForAppointmentSetting(plat, OrderGateTypeConsts.GATE_PLAT_BACKSTAGE, ConfOrderDutyConsts.APPOINTMENT_OR_CHANGE_APPOINTMENT);
        if (orderDuty == null) {
            orderScheduleVO.setTimes(scheTimes);
            return orderScheduleVO;
        }

        // 预约时间范围
        scheTimes = this.filterScheTimes(orderDuty.getStartTime(), orderDuty.getEndTime(), scheTimes);
        orderScheduleVO.setTimes(scheTimes);
        return orderScheduleVO;
    }

    /**
     * 是否计算排期时间
     * @param workOrderScheduleQuery
     * @param curDate
     * @return
     */
    private Boolean isCalculateSchedule(WorkOrderScheduleQuery workOrderScheduleQuery, Date curDate) {
        Date startTime = DateUtil.getDateStart(curDate);
        Date endTime = DateUtil.getDateEnd(DateUtil.getNowDefer(6));
        // 是否在当前时间开始7天内
        if (DateUtil.isBetween(startTime, endTime, DateUtil.parse(workOrderScheduleQuery.getScheDate(), DateUtil.FORMAT_DATE))) {
            // 当天是否有工程师可派-网格组派单
            return gridGroupDistributeBService.checkGridGroupTodayAvailable(workOrderScheduleQuery);
        }
        return Boolean.TRUE;
    }

    /**
     * 判断当前时间是否可以操作预约时间
     *
     * @param orderDuty
     * @return true 可以操作
     */
    private boolean validateOperateDutyTime(OrderDuty orderDuty) {
        if (orderDuty == null || StringUtils.isBlank(orderDuty.getStartTime()) || StringUtils.isBlank(orderDuty.getEndTime())) {
            return true;
        }
        String nowMinute = DateUtil.toString(new Date(), "HH:mm");
        if (this.isBetweenMinute(nowMinute, orderDuty.getStartTime(), orderDuty.getEndTime())) {
            return true;
        }
        return false;
    }

    /**
     * 调服务查通用设置的预约时间、改约时间、改约次数
     *
     * @param plat
     * @param gateType
     * @param appointmentOrChange 1：预约，2：改约
     * @return
     */
    private OrderDuty callServeForAppointmentSetting(int plat, int gateType, Integer appointmentOrChange) {
        OrderDutyQuery orderDutyQuery = new OrderDutyQuery();
        orderDutyQuery.setPlat(plat);
        orderDutyQuery.setType(gateType);
        orderDutyQuery.setAppointmentOrChange(appointmentOrChange);
        log.info("orderDutyService#listByQuery 入参:[{}]", orderDutyQuery);
        List<OrderDuty> orderDutyList = orderDutyService.listByQuery(orderDutyQuery);
        log.info("orderDutyService#listByQuery 出参:[{}]", orderDutyList);
        if (CollectionUtils.isNotEmpty(orderDutyList)) {
            return orderDutyList.get(0);
        }

        return null;
    }


    /**
     * 计算过滤的后的预约时间区间
     *
     * @param startTime
     * @return
     */
    private String filterScheTimes(String startTime, String endTime, String time) {
        int frontIndex = calIndex_96(startTime, 0);
        int afterIndex = calIndex_96(endTime, 1);
        return OrderConsts.ORDER_SCHE_NONE_TIMES_96.substring(0, frontIndex) + time.substring(frontIndex, afterIndex) +
                OrderConsts.ORDER_SCHE_NONE_TIMES_96.substring(afterIndex);
    }

    /**
     * 计算时间区间前后的指针位置
     * @param time
     * @return
     */
    private static int calIndex(String time, int temp) {
        int timeHour = Integer.parseInt(time.substring(0, time.indexOf(":")));
        int timeMinute = Integer.parseInt(time.substring(time.indexOf(":") + 1));

        if (timeMinute != 0 && timeMinute != 30) {
            if (temp < 1) {
                if (timeMinute < 30) {
                    timeMinute = 30;
                } else {
                    timeMinute = 0;
                    timeHour = timeHour + 1;
                }
            } else {
                if (timeMinute < 30) {
                    timeMinute = 0;
                } else {
                    timeMinute = 30;
                }
            }
        }

        int index = timeHour * 2;

        if (timeMinute >= 30) {
            index = index + 1;
        }

        return index;
    }

    /**
     * 计算时间区间前后的指针位置
     * @param time
     * @return
     */
    private static int calIndex_96(String time, int temp) {
        int timeHour = Integer.parseInt(time.substring(0, time.indexOf(":")));
        int timeMinute = Integer.parseInt(time.substring(time.indexOf(":") + 1));

        int minuteIndex = 0;

        if (temp < 1) {
            minuteIndex = timeMinute == 0 ? 0 : timeMinute / 15 + 1;
        } else {
            minuteIndex = timeMinute / 15;
        }

        return timeHour * 4 + minuteIndex;
    }

    /**
     * 判断修改次数是否达到最大值
     *
     * @param orderId
     * @param orderDuty
     * @return true 可以修改，false 超过次数不能修改
     */
    private boolean checkModifyCount(Long orderId, OrderDuty orderDuty) {
        if (orderDuty == null || NumberUtil.isNullOrZero(orderDuty.getNumberOfContractChanges())) {
            return true;
        }

        if (NumberUtil.isNullOrZero(orderId)) {
            return true;
        }

        OrderChangeRecord orderChangeRecord = orderChangeRecordService.getChangeRecordByOrderId(orderId);
        if (orderChangeRecord == null) {
            return true;
        }

        switch (orderDuty.getType()) {
            case OrderGateTypeConsts.GATE_APP:
                return orderChangeRecord.getAppDutyTimeModifyCount() < orderDuty.getNumberOfContractChanges();
            case OrderGateTypeConsts.GATE_PLAT_BACKSTAGE:
                return orderChangeRecord.getPlatDutyTimeModifyCount() < orderDuty.getNumberOfContractChanges();
            case OrderGateTypeConsts.GATE_PORTAL_SP:
                return orderChangeRecord.getSpPopDutyTimeModifyCount() < orderDuty.getNumberOfContractChanges();
            case OrderGateTypeConsts.GATE_PORTAL_FC:
                return orderChangeRecord.getFcPopDutyTimeModifyCount() < orderDuty.getNumberOfContractChanges();
            default:
                return true;
        }
    }

    /**
     * 分钟分钟
     *
     * @param minute
     * @param minMinute
     * @param maxMinute
     * @return
     */
    private boolean isBetweenMinute(String minute, String minMinute, String maxMinute){
        int m = Integer.parseInt(minute.replace(":", ""));
        int min = Integer.parseInt(minMinute.replace(":", ""));
        int max = Integer.parseInt(maxMinute.replace(":", ""));
        return  m >= min && m <= max;
    }

    private ScheduleDayVo getDate(int count) {
        ScheduleDayVo scheduleDayVo = new ScheduleDayVo();
        Date date = DateUtil.getNowDefer(count);
        String year = DateUtil.toString(date, DateUtil.FORMAT_DATE);
        scheduleDayVo.setDate(year);
        scheduleDayVo.setWeek(DateUtil.getWeekOfDate(date));
        return scheduleDayVo;
    }

    /**
     * 处理可预约时间
     * <p>预约时间是当天,可选预约时间推后1个半小时。<p/>
     *
     * @param scheDateStr
     * @return
     */
    private String processSchedule(String scheDateStr) {
        Date curDate = DateUtil.getNow();

        int curDay = Integer.parseInt(DateUtil.toString(curDate, DateUtil.FORMAT_DATE2));
        int scheDay = Integer.parseInt(DateUtil.toString(DateUtil.parse(scheDateStr, DateUtil.FORMAT_DATE), DateUtil.FORMAT_DATE2));
        if (scheDay < curDay) {
            return OrderConsts.ORDER_SCHE_NONE_TIMES;
        }
        //限制服务的时间（半小时/单位）
        int limitServiceTimes = 0;
        if (scheDay == curDay) {
            limitServiceTimes = this.getLimitServiceTimes(curDate);
        }
        String scheTimes = OrderConsts.ORDER_SCHE_ALL_TIMES;
        if (limitServiceTimes > 0) {
            scheTimes = OrderConsts.ORDER_SCHE_NONE_TIMES.substring(0, limitServiceTimes) + OrderConsts.ORDER_SCHE_ALL_TIMES.substring(limitServiceTimes);
        }
        return scheTimes;
    }

    /**
     * 获取当前时间点
     *
     * @param curDate
     * @return
     */
    private int getLimitServiceTimes(Date curDate) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(curDate);
        int nowHour = calendar.get(Calendar.HOUR_OF_DAY);
        int nowMinute = calendar.get(Calendar.MINUTE);
        // 分钟数
        return nowHour * 4 + nowMinute / 15 + 1;
    }
}
